Skip to content

Fix FragmentfailureRampdown thread safety and divide-by-zero#1371

Open
benmesander wants to merge 2 commits intodev_sprint_25_2from
feature/VPAAMP-210
Open

Fix FragmentfailureRampdown thread safety and divide-by-zero#1371
benmesander wants to merge 2 commits intodev_sprint_25_2from
feature/VPAAMP-210

Conversation

@benmesander
Copy link
Copy Markdown
Contributor

Add mProfileLock guard when copying mProfiles in
FragmentfailureRampdown. The vector was previously copied without holding the lock, which is undefined behavior if another thread calls clearProfiles()/addProfile() concurrently during a period transition.

Add early return when abrMaxBuffer <= 0 to prevent floating-point divide-by-zero when computing buffer percentage. The AampAbrConfig constructor initializes abrMaxBuffer to 0, so if ReadPlayerConfig has not been called, the division produces Inf.

For the legacy ABR, add a protected getProfileInfoLocked() helper to ABRManager so HybridABRManager can obtain a thread-safe copy of mProfiles without accessing private members directly.

These races are extremely unlikely to manifest, but are addressed here for reasons of code correctness and future proofing.

Applied to both new ABR (abr/abr.cpp) and legacy ABR (support/aampabr/HybridABRManager.cpp, ABRManager.h/cpp). L1 tests added for the abrMaxBuffer guard.

Add mProfileLock guard when copying mProfiles in
FragmentfailureRampdown. The vector was previously copied without
holding the lock, which is undefined behavior if another thread
calls clearProfiles()/addProfile() concurrently during a period
transition.

Add early return when abrMaxBuffer <= 0 to prevent floating-point
divide-by-zero when computing buffer percentage. The AampAbrConfig
constructor initializes abrMaxBuffer to 0, so if ReadPlayerConfig
has not been called, the division produces Inf.

For the legacy ABR, add a protected getProfileInfoLocked() helper
to ABRManager so HybridABRManager can obtain a thread-safe copy
of mProfiles without accessing private members directly.

These races are extremely unlikely to manifest, but are addressed here
for reasons of code correctness and future proofing.

Applied to both new ABR (abr/abr.cpp) and legacy ABR
(support/aampabr/HybridABRManager.cpp, ABRManager.h/cpp).
L1 tests added for the abrMaxBuffer guard.
@benmesander benmesander requested a review from a team as a code owner April 27, 2026 19:04
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR hardens ABR rampdown logic by fixing a thread-safety issue when copying the profile list during FragmentfailureRampdown, and by preventing a floating-point divide-by-zero when abrMaxBuffer is unset/zero. It also adds unit tests to validate the new guard behavior.

Changes:

  • Add abrMaxBuffer <= 0 guard in FragmentfailureRampdown to avoid divide-by-zero (new and legacy ABR).
  • Make copying of mProfiles thread-safe during rampdown (new ABR via lock; legacy ABR via new locked accessor).
  • Add L1 unit tests covering the abrMaxBuffer == 0 rampdown behavior.

Reviewed changes

Copilot reviewed 6 out of 6 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
abr/abr.cpp Adds abrMaxBuffer guard and locks mProfiles while copying in FragmentfailureRampdown.
support/aampabr/HybridABRManager.cpp Adds abrMaxBuffer guard and uses a new locked profile-copy helper in rampdown.
support/aampabr/ABRManager.h Adds getProfileInfoLocked() API for thread-safe access to the profile list.
support/aampabr/ABRManager.cpp Implements getProfileInfoLocked() by copying mProfiles under mProfileLock.
test/utests/tests/AampAbrTests/AbrTests.cpp Adds a unit test asserting rampdown returns 0 when abrMaxBuffer == 0 (new ABR).
test/utests/tests/AampAbrTests/HybridAbrTests.cpp Adds a unit test asserting rampdown returns 0 when abrMaxBuffer == 0 (legacy ABR).

Comment on lines +294 to +298
/**
* @brief Get a thread-safe copy of the profile list
* @return Copy of mProfiles taken under mProfileLock
*/
std::vector<ProfileInfo> getProfileInfoLocked();
Comment thread abr/abr.cpp
Comment on lines +1123 to +1124
AAMPLOG_ERR("abrMaxBuffer is %d, cannot compute buffer percentage",
eAAMPAbrConfig.abrMaxBuffer);
Comment thread abr/abr.cpp
Comment on lines 1117 to +1121
* @return - desired profile based on buffer
*/
BitsPerSecond ABRManager::FragmentfailureRampdown(int currentBuffer, int currentProfileIndex)
{
if (eAAMPAbrConfig.abrMaxBuffer <= 0)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants